package com.efamily.ewallet.client.account;

import java.util.List;

import com.efamily.ewallet.client.account.bean.AccountBean;
import com.efamily.ewallet.client.account.bean.AccountBean.Gender;
import com.efamily.ewallet.client.account.service.AccountManagerServiceAsync;
import com.efamily.ewallet.client.common.DefaultAsyncCallback;
import com.efamily.ewallet.client.exception.WrongAccountNameException;
import com.extjs.gxt.ui.client.Style.Scroll;
import com.extjs.gxt.ui.client.event.BaseEvent;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.widget.Composite;
import com.extjs.gxt.ui.client.widget.MessageBox;
import com.extjs.gxt.ui.client.widget.Window;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.FieldSet;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.NumberField;
import com.extjs.gxt.ui.client.widget.form.SimpleComboBox;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.FormData;
import com.extjs.gxt.ui.client.widget.layout.FormLayout;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Anchor;

public class RegisterAccountWindow extends Window {
	private RegisterAccountForm form = new RegisterAccountForm();
	AccountBean accountBean = new AccountBean();
	static RegisterAccountWindow registerAccountWindow;
	public static RegisterAccountWindow getInstance(){
		if (registerAccountWindow == null) {
			registerAccountWindow = new RegisterAccountWindow();
		}
		return registerAccountWindow;
	}

	private RegisterAccountWindow() {
		setSize(500, 400);
		setPlain(true);
		setResizable(false);
		setClosable(true);
		setModal(true);
		setBlinkModal(true);
		setHeading("Create new account");
		setLayout(new FitLayout());
		add(form);
	}

	private class RegisterAccountForm extends Composite {
		private AccountManagerServiceAsync balanceService = AccountManagerServiceAsync.instance;
		private FormPanel formPanel = new FormPanel();
		private TextField<String> nickNameFld = new TextField<String>();
		private Anchor verifyNickLink = new Anchor("Check existing");
		private TextField<String> passwordFld = new TextField<String>();
		private TextField<String> confirmPasswordFld = new TextField<String>();
		private TextField<String> mailFld = new TextField<String>();
		private SimpleComboBox<String> countryCmb = new SimpleComboBox<String>();
		private TextField<String> occupationFld = new TextField<String>();
		private NumberField ageFld = new NumberField();
		private SimpleComboBox<Gender> genderCmb = new SimpleComboBox<Gender>();
		private FormData formData = new FormData("-20");
		private Button saveBtn = new Button("Save");
		private final AccountManagerServiceAsync accountManagerService = AccountManagerServiceAsync.instance;

		public RegisterAccountForm() {
			buildForm();
			initComponent(formPanel);
			this.addListener(Events.Attach, new Listener<BaseEvent>() {
				public void handleEvent(BaseEvent be) {
					nickNameFld.reset();
					passwordFld.reset();
					confirmPasswordFld.reset();
					mailFld.reset();
					countryCmb.reset();
					occupationFld.reset();
					ageFld.reset();
					genderCmb.reset();
				}
			});
		}

		private void buildForm() {

			nickNameFld.setFieldLabel("NickName*");
			nickNameFld.setAllowBlank(false);

			FieldSet requiredFieldSet = new FieldSet();
			requiredFieldSet.setHeading("Required Information");

			FormLayout requiredSetlayout = new FormLayout();
			requiredSetlayout.setLabelWidth(120);
			requiredFieldSet.setLayout(requiredSetlayout);
			requiredFieldSet.add(nickNameFld, formData);
			verifyNickLink.addClickHandler(new ClickHandler() {
				public void onClick(ClickEvent event) {
					String nickname = nickNameFld.getValue();
					if (nickname != null && !nickname.isEmpty()) {
						accountManagerService.verifyNickName(nickNameFld
								.getValue(),
								new DefaultAsyncCallback<Boolean>() {
									@Override
									public void onSuccess(Boolean result) {
										if (!result) {
											nickNameFld
													.markInvalid("You can not use this NickName");
										}
									}
								});
					} else {
						nickNameFld.markInvalid("NickName can not be empty");
					}
				}
			});
			requiredFieldSet.add(verifyNickLink);

			passwordFld.setFieldLabel("Password");
			passwordFld.setPassword(true);
			confirmPasswordFld.setFieldLabel("Confirm Password");
			confirmPasswordFld.setPassword(true);
			mailFld.setFieldLabel("Mail");
			countryCmb.setFieldLabel("Country");
			countryCmb.setForceSelection(true);
			countryCmb.setTypeAhead(true);
			balanceService
					.getCountriesList(new DefaultAsyncCallback<List<String>>() {
						@Override
						public void onSuccess(List<String> countries) {
							countryCmb.add(countries);
						}
					});

			occupationFld.setFieldLabel("Occupation");
			ageFld.setFieldLabel("Age");
			ageFld.setAllowNegative(false);
			ageFld.setAllowDecimals(false);
			ageFld.setOriginalValue(null);
			genderCmb.setFieldLabel("Gender");
			genderCmb.add(AccountBean.Gender.MALE);
			genderCmb.add(AccountBean.Gender.FEMALE);

			FieldSet optionalFieldSet = new FieldSet();
			optionalFieldSet.setHeading("Optional Information");
			optionalFieldSet.setScrollMode(Scroll.AUTO);
			FormLayout optionalSetLayout = new FormLayout();
			optionalSetLayout.setLabelWidth(120);
			optionalFieldSet.setLayout(optionalSetLayout);

			optionalFieldSet.add(passwordFld, formData);
			optionalFieldSet.add(confirmPasswordFld, formData);
			optionalFieldSet.add(mailFld, formData);
			optionalFieldSet.add(countryCmb, formData);
			optionalFieldSet.add(occupationFld, formData);
			optionalFieldSet.add(ageFld, formData);
			optionalFieldSet.add(genderCmb, formData);

			formPanel.setHeaderVisible(false);
			formPanel.add(requiredFieldSet);
			formPanel.add(optionalFieldSet);
			saveBtn.addSelectionListener(new SelectionListener<ButtonEvent>() {
				@Override
				public void componentSelected(ButtonEvent ce) {
					try {
						if (validateForm()) {
							createAccount();
						}
					} catch (Exception ex) {
						MessageBox.alert("Operation failed", ex.getMessage(),
								null);
						ex.printStackTrace();
					}
				}
			});
			formPanel.addButton(saveBtn);
		}

		private void createAccount() {
			if (validateForm()) {
				accountBean.setNickName(nickNameFld.getValue());
				if (ageFld.getValue() != null)
					accountBean.setAge(ageFld.getValue().intValue());
				if (countryCmb.getValue() != null)
					accountBean.setCountry(countryCmb.getValue().getValue());
				accountBean.setOccupation(occupationFld.getValue());
				if (genderCmb.getValue() != null)
					accountBean.setGender(genderCmb.getValue().getValue());
				accountManagerService.createAccount(accountBean, passwordFld
						.getValue(), mailFld.getValue(),
						new DefaultAsyncCallback<Void>() {
							@Override
							public void onFailure(Throwable ex) {
								if (ex instanceof WrongAccountNameException) {
									nickNameFld
											.markInvalid("You can not use this NickName");
								} else {
									super.onFailure(ex);
								}
							}

							@Override
							public void onSuccess(Void arg0) {
								RegisterAccountWindow.this.hide();
							}
						});

			}

		}

		private boolean validateForm() {
			boolean result = true;
			String nickname = nickNameFld.getValue();
			if (nickname == null || nickname.isEmpty()) {
				nickNameFld.markInvalid("NickName can not be empty");// forceInvalid();
				result = false;
			}
			String password = passwordFld.getValue();
			String passConfirmation = confirmPasswordFld.getValue();
			if (password != null && !password.equals(passConfirmation)) {
				confirmPasswordFld
						.markInvalid("Confirmation value should be equal password vale.");
				result = false;
			}

			return result;
		}

	}

}
